﻿#include "maindesigner.h"
#include "ui_maindesigner.h"

MainDesigner::MainDesigner(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainDesigner)
    , isWaitingResponse(false)
{
    ui->setupUi(this);
    // 设置日志窗口默认字体（确保中文显示正常）
    m_defaultCodec = QTextCodec::codecForName("GB18030");   //windows系统默认编码
    QFont logFont("Microsoft YaHei", 9); // Windows
    ui->txt_log->setFont(logFont);
    ui->txt_log->document()->setMaximumBlockCount(1000); // 另一种日志限制方式
    m_tableWidget = ui->testFunTab;
    InitTestFunTable();
    responseTimer = new QTimer(this);
    responseTimer->setSingleShot(true);
    connect(responseTimer, &QTimer::timeout, this, &MainDesigner::onSendTimeout);

    // 初始化配置视图管理器
    m_configViewManager = new ConfigViewManager(ui->stackedWidget, this);

    // 连接视图切换按钮
    connect(ui->btnGroupView, &QPushButton::clicked, this,&MainDesigner::on_btnGroupView_clicked);
    connect(ui->btnPropertyView, &QPushButton::clicked, this, [this](){m_configViewManager->setCurrentView(ConfigViewType::PropertyView);});
    connect(ui->btnJsonView, &QPushButton::clicked, this, [this](){m_configViewManager->setCurrentView(ConfigViewType::JsonView);});
    connect(ui->btnCardView, &QPushButton::clicked, this, [this](){m_configViewManager->setCurrentView(ConfigViewType::CardView);});
    connect(m_configViewManager, &ConfigViewManager::sendConfigRequested, this, [this](const QJsonArray &config){
        QJsonDocument json_doc = QJsonDocument(config);
        QByteArray json_data = json_doc.toJson();
        emit sig_serialWrite(json_data);
    });
}

MainDesigner::~MainDesigner()
{
    delete ui;
}

void MainDesigner::parseJsonDate(const QByteArray &json_data)
{
    QJsonParseError parse_error;
    QJsonDocument doc = QJsonDocument::fromJson(json_data,&parse_error);
    if( parse_error.error!=QJsonParseError::NoError ) {
        slots_displayLog("json解析错误:"+parse_error.errorString().toUtf8(),Qt::red);
        return;
    }
    if( !doc.isObject() ) {
        slots_displayLog("json数据不是对象格式");
        return;
    }
    QJsonObject root_obj = doc.object();
    //解析测试函数表
    if( root_obj.contains("test_fun") ) {
        test_fun_tab.clear();
        test_fun_tab = ParseTestFunArray(root_obj["test_fun"].toArray());
        ui->testFunTab->setRowCount(1);
        AddTestFunButton(test_fun_tab);
    }
    // 获取配置数组
    if (root_obj.contains("config_fun") && root_obj["config_fun"].isArray()) {
        QJsonArray configArray = root_obj["config_fun"].toArray();
        m_configViewManager->updateConfig(configArray);
    }
}

void MainDesigner::InitTestFunTable()
{
    // 设置表格基本属性
    m_tableWidget->setColumnCount(2);
    m_tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
    m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_tableWidget->setFocusPolicy(Qt::NoFocus);
    m_tableWidget->verticalHeader()->setVisible(false);

    // 设置第一列固定宽度
    m_tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
    m_tableWidget->setColumnWidth(0, 60);  // 固定宽度250px

    // 设置第二列自适应
    m_tableWidget->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);

    // 设置表头
    //m_tableWidget->setHorizontalHeaderLabels({"指令值", "操作"});
    setHeaderNames("指令", "功能");
    // 样式设置 - 完全禁用指令列的交互和焦点
    m_tableWidget->setStyleSheet(
        "QTableWidget {"
        "   background-color: #f8f8f8;"
        "   gridline-color: #e0e0e0;"
        "   border: none;"
        "   outline: none;"  // 移除焦点框
        "}"
        "QTableWidget::item {"
        "   padding: 5px;"
        "   background-color: #f0f0f0;"  // 灰色背景表示不可交互
        "   color: #333333;"             // 深色文字
        "   border: none;"               // 移除边框
        "}"
        "QTableWidget::item:first {"
        "   background-color: #f0f0f0;"  // 确保第一列有背景色
        "}"
        // 完全禁用焦点效果
        "QTableWidget::item:focus {"
        "   outline: none;"
        "   border: none;"
        "}"
        // 禁用第一列的所有交互
        "QTableWidget::item[column=\"0\"] {"
        "   cursor: default;"           // 默认光标（非指针）
        "}"
        // 完全禁用选择效果
        "QTableWidget::item:selected {"
        "   background-color: #f0f0f0;" // 总是显示灰色背景
        "   color: #333333;"
        "}"
        "QHeaderView::section {"
        "   background-color: #e0e0e0;"
        "   padding: 5px;"
        "   border: none;"
        "   font-weight: bold;"
        "   text-align: center;"
        "}"
        // 按钮焦点样式
        "QPushButton:focus {"
        "   outline: none;"  // 移除按钮的焦点虚线
        "}"
    );

}

void MainDesigner::setHeaderNames(const QString &commandHeader, const QString &actionHeader)
{
    if (m_tableWidget) {
        // 设置表头标签
        QStringList headers;
        headers << commandHeader << actionHeader;
        m_tableWidget->setHorizontalHeaderLabels(headers);
    }
}

void MainDesigner::AddTestFunButton(const QList<_fun_tab_struct> &fun_list)
{
    if (!ui->testFunTab) return;
    for( const _fun_tab_struct &temp_fun : fun_list ) {
        // 插入新行
        int row = ui->testFunTab->rowCount();
        ui->testFunTab->insertRow(row);
        // 第一列：指令值
        QTableWidgetItem *commandItem = new QTableWidgetItem(temp_fun.cmd);
        commandItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
        // 完全禁用交互 - 移除所有标志
        commandItem->setFlags(Qt::NoItemFlags);
        commandItem->setFlags(Qt::ItemIsEnabled);  // 不可编辑
        commandItem->setData(Qt::UserRole, QString(temp_fun.cmd));  // 存储原始命令
        commandItem->setTextAlignment(Qt::AlignCenter);  // 设置为居中
        ui->testFunTab->setItem(row, 0, commandItem);
        // 第二列：按钮
        QPushButton *actionButton = new QPushButton(temp_fun.info,ui->testFunTab);

        // 计算按钮所需宽度
        QFontMetrics fm(actionButton->font());
        //int buttonWidth = fm.horizontalAdvance(temp_fun.info) + 30;  // 文本宽度 + 边距
        // 设置按钮固定宽度
        //actionButton->setFixedWidth(buttonWidth);
        actionButton->setStyleSheet("QPushButton { text-align: left; padding: 5px; }");
        actionButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

        // 存储行号信息到按钮属性
        actionButton->setProperty("btnName", temp_fun.info);
        actionButton->setProperty("keyName", temp_fun.name);
        keyButtons.insert(temp_fun.name,actionButton);
        connect(actionButton, &QPushButton::clicked, this, &MainDesigner::onKeyButtonClicked);
        // 将按钮添加到表格
        ui->testFunTab->setCellWidget(row, 1, actionButton);
        // 设置行高
        ui->testFunTab->setRowHeight(row, 40);
    }
}

QList<_fun_tab_struct> MainDesigner::ParseTestFunArray(const QJsonArray &func_array)
{
    QList<_fun_tab_struct> temp_list;
    _fun_tab_struct temp_fun;
    for(const QJsonValue &fun_value : func_array ) {
        QJsonObject obj = fun_value.toObject();
        temp_fun.name = obj["name"].toString();
        temp_fun.info = obj["info"].toString();
        temp_fun.cmd = obj["cmd"].toString();
        temp_list.append(temp_fun);
    }
    return temp_list;
}

// 日志裁剪函数
void MainDesigner::trimLogContent()
{
    QTextDocument* doc = ui->txt_log->document();
    const int MAX_LINES = 500;   // 最大行数限制
    const int MAX_CHARS = 20000; // 最大字符数限制
    if (doc->blockCount() > MAX_LINES || doc->characterCount() > MAX_CHARS) {
        QTextCursor cursor(doc);
        cursor.beginEditBlock(); // 开始事务操作
        // 计算要删除的行数（保留90%的内容）
        int linesToRemove = doc->blockCount() - static_cast<int>(MAX_LINES * 0.9);
        if (linesToRemove > 0) {
            cursor.movePosition(QTextCursor::Start);
            // 移动到要保留的起始位置
            for (int i = 0; i < linesToRemove; ++i) {
                if (!cursor.movePosition(QTextCursor::NextBlock)) {
                    break;
                }
            }
            // 选择并删除前面的内容
            cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
            cursor.removeSelectedText();
        }
        cursor.endEditBlock(); // 结束事务操作
    }
}

// 日志显示槽函数
void MainDesigner::slots_displayLog(const QByteArray &txt, QColor color)
{
    // 线程安全检查（Release模式也生效）
    if (QThread::currentThread() != QApplication::instance()->thread()) {
        QMetaObject::invokeMethod(this, "slots_DisplayLog",
                                  Qt::QueuedConnection,
                                  Q_ARG(QByteArray, txt),
                                  Q_ARG(QColor, color));
        return;
    }
    // 1. 智能解码
    //QString text = decodeWithFallback(txt);
    // 2. 准备时间戳
    QString timestamp = QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss ");
    // 3. 控制日志长度
    trimLogContent();
    // 4. 高性能文本插入
    QTextCursor cursor(ui->txt_log->document());
    cursor.movePosition(QTextCursor::End);
    // 插入时间戳（灰色）
    QTextCharFormat timeFormat;
    timeFormat.setForeground(Qt::gray);
    cursor.setCharFormat(timeFormat);
    cursor.insertText(timestamp);
    // 插入日志内容（带颜色）
    QTextCharFormat textFormat;
    if (color.isValid() && color.alpha() > 0) {
        textFormat.setForeground(color);
        // 可选：设置背景色或字体
        // textFormat.setBackground(QColor(255, 255, 200));
        // textFormat.setFontWeight(QFont::Bold);
    }
    cursor.setCharFormat(textFormat);
    cursor.insertText(txt);
    // 添加换行
    cursor.insertText("\n");
    // 5. 自动滚动到底部
    //ui->txt_log->ensureCursorVisible();
    ui->txt_log->moveCursor(ui->txt_log->textCursor().End);
}

void MainDesigner::slots_serialRead(QByteArray data)
{
    //设置编码为UTF-8
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    QTextCodec *gbk_code = QTextCodec::codecForName("GBK");
    QString de_str = gbk_code->toUnicode(data);
    QByteArray utf8_data = de_str.toUtf8();
    //slots_displayLog(" <- "+utf8_data,Qt::black);
    if (isWaitingResponse) {
        processResponse(data);
        return;
    }
    parseJsonDate(utf8_data);
}

void MainDesigner::onResponseReceived()
{
    slots_displayLog("响应处理完成，准备下一步操作...");
}

void MainDesigner::onSendTimeout()
{
    if (!isWaitingResponse) return;
        QString msg = QString("× 请求超时: " + currentRequestKey);
        slots_displayLog(msg.toUtf8(),Qt::red);
        // 恢复按钮状态
        if (keyButtons.contains(currentRequestKey)) {
            QPushButton *btn = keyButtons.value(currentRequestKey);
            btn->setEnabled(true);
            btn->setText(btn->property("btnName").toString());
        }
        // 重置状态
        isWaitingResponse = false;
        currentRequestKey.clear();
}

void MainDesigner::onKeyButtonClicked()
{
    QPushButton *btn = qobject_cast<QPushButton*>(sender());
    if (!btn || isWaitingResponse) return;

        QString key = btn->property("keyName").toString();
        QString btn_name = btn->property("btnName").toString();
        // 发送请求
        sendRequest(key.toUtf8());
        currentRequestKey = key;

        // 更新按钮状态
        btn->setEnabled(false);
        btn->setText(btn_name + " (等待响应)");
        QString msg = QString(">> 发送: " + key +
                                  " [键: " + key + "]");
        slots_displayLog(msg.toUtf8(),Qt::green);
        return;
}

void MainDesigner::sendRequest(const QByteArray &data)
{
    // 设置等待状态
    isWaitingResponse = true;
    lastRequestData = data;
    // 启动超时定时器 (5秒超时)
    responseTimer->start(5000);
    // 在串口线程中发送数据
    emit sig_serialWrite(data);
}

void MainDesigner::processResponse(const QByteArray &data)
{
    // 检查是否匹配请求
    bool isMatch = false;
    // 简单匹配逻辑
    if (data.contains(lastRequestData)) {
        isMatch = true;
    } else {
        // 这里可以添加更复杂的匹配逻辑
        isMatch = true; // 简化处理
    }
    if (isMatch) {
        // 停止定时器
        responseTimer->stop();
        // 更新UI
        QString msg = QString("√ 收到响应: " + QString::fromUtf8(data));
        slots_displayLog(msg.toUtf8(),Qt::blue);
        // 恢复按钮状态
        if (keyButtons.contains(currentRequestKey)) {
            QPushButton *btn = keyButtons.value(currentRequestKey);
            btn->setEnabled(true);
            btn->setText(btn->property("btnName").toString());
        }
        // 重置状态
        isWaitingResponse = false;
        currentRequestKey.clear();
        // 触发下一步操作
        QTimer::singleShot(0, this, &MainDesigner::onResponseReceived);
    }
}

void MainDesigner::on_btnGroupView_clicked()
{
    m_configViewManager->setCurrentView(ConfigViewType::GroupView);
}
